home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / answrbok / 8_13.lha / 8_13 / 8_13a.c next >
C/C++ Source or Header  |  1993-08-08  |  5KB  |  283 lines

  1. * Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
  2. * The C++ Answer Book */
  3. * Tony Hansen */
  4. * All rights reserved. */
  5. / match a pattern on the input stream
  6. / %d looks for an integer & stops at the first
  7. /    non-integer character
  8. / %o looks for an octal integer & stops ...
  9. / %x looks for a hexadecimal integer & stops ...
  10. / %i looks for a C++ integer & stops ...
  11. / %f looks for a floating point number & stops ...
  12. / %c matches a single character
  13. / %[xyz] matches a character within the set
  14. / %[^xyz] matches a character not within the set
  15. / %s matches a white-space delineated string
  16. / % may be followed by a field width
  17. / %% matches %
  18. / ' ' matches any white space
  19. / 'X' matches the character X
  20.  
  21. include <pat.h>    /* DELETE */
  22. include <ctype.h>    /* DELETE */
  23. include <limits.h>    /* DELETE */
  24. include <stdlib.h>    /* DELETE */
  25. include "8_13b.c"    /* DELETE */
  26. nt pat::match(char *pattern)
  27.  
  28.    // reset base ptr to pt to beginning of buffer
  29.    ebp->setbuffering();
  30.  
  31.    // loop through the pattern looking
  32.    // for things to match.
  33.    int goodpattern = 1;
  34.    while (*pattern && goodpattern)
  35. {
  36. int c = ebp->sgetc();
  37. char p = *pattern++;
  38.  
  39. / define a couple of small macros for
  40. / some common sequences
  41. define Next()                \
  42.    ebp->stossc(), c = ebp->sgetc()
  43.  
  44. define WNext()                \
  45.    width--, ebp->stossc(), c = ebp->sgetc()
  46.  
  47. define doloop(testfunc)        \
  48.    do { Next(); } while (testfunc(c))
  49.  
  50. define dowloop(testfunc)        \
  51.    do { width--; ebp->stossc();    \
  52.    } while ((width > 0) &&        \
  53.      testfunc(c = ebp->sgetc()))
  54.  
  55. switch (p)
  56.     {
  57.     // space matches arbitrary white space
  58.     case ' ':
  59.     if (isspace(c))
  60.         doloop(isspace);
  61.  
  62.     else
  63.         goodpattern = 0;
  64.     break;
  65.  
  66.     // a pattern: %d, %f, %c, %s, %%
  67.     case '%':
  68.     p = *pattern++;
  69.  
  70.     // check pattern for a field
  71.     // width specification
  72.     long width = LONG_MAX;
  73.     if (isdigit(p))
  74.         {
  75.         width = strtol(&pattern[-1],
  76.         &pattern, 10);
  77.         p = *pattern++;
  78.         }
  79.  
  80.     // the default for these two is 1
  81.     else if ((p == '[') || (p == 'c'))
  82.         width = 1;
  83.  
  84.     // check for patterns which
  85.     // toss white space first
  86.     switch (p)
  87.         {
  88.         case 'd': case 'f':
  89.         case 'o': case 'x':
  90.         case 'i': case 's':
  91.         if (isspace(c))
  92.             doloop(isspace);
  93.         }
  94.  
  95.     // now skip past the particular type
  96.     switch (p)
  97.         {
  98.         // decimal number
  99.         case 'd':
  100.         if ((width > 0) &&
  101.             ((c == '-') || (c == '+')))
  102.             WNext();
  103.  
  104.         if ((width > 0) && isdigit(c))
  105.             dowloop(isdigit);
  106.  
  107.         else
  108.             goodpattern = 0;
  109.         break;
  110.  
  111.         // octal number
  112.         case 'o':
  113.         if ((width > 0) &&
  114.             ((c == '-') || (c == '+')))
  115.             WNext();
  116.  
  117.         if ((width > 0) && isodigit(c))
  118.             dowloop(isodigit);
  119.  
  120.         else
  121.             goodpattern = 0;
  122.         break;
  123.  
  124.         // hexdecimal number
  125.         case 'x':
  126.         if ((width > 0) &&
  127.             ((c == '-') || (c == '+')))
  128.             WNext();
  129.  
  130.         if ((width > 0) && isxdigit(c))
  131.             dowloop(isxdigit);
  132.  
  133.         else
  134.             goodpattern = 0;
  135.         break;
  136.  
  137.         // decimal, octal or hex number
  138.         case 'i':
  139.         if ((width > 0) &&
  140.             ((c == '-') || (c == '+')))
  141.             WNext();
  142.  
  143.         // check for leading 0 or 0x
  144.         if ((width > 0) && (c == '0'))
  145.             {
  146.             WNext();
  147.  
  148.             if ((width > 0) &&
  149.             ((c == 'x') || (c == 'X')))
  150.             WNext();
  151.             }
  152.  
  153.         if ((width > 0) && isdigit(c))
  154.             dowloop(isdigit);
  155.  
  156.         else
  157.             goodpattern = 0;
  158.         break;
  159.  
  160.         // floating point
  161.         case 'f':
  162.         if ((width > 0) &&
  163.             ((c == '-') || (c == '+')))
  164.             WNext();
  165.  
  166.         int digitsbefore = 0;
  167.         int hasdecimal = 0;
  168.         int digitsafter = 0;
  169.         int hasexponent = 0;
  170.  
  171.         if ((width > 0) && isdigit(c))
  172.             {
  173.             digitsbefore = 1;
  174.             dowloop(isdigit);
  175.             }
  176.  
  177.         if ((width > 0) && (c == '.'))
  178.             {
  179.             hasdecimal = 1;
  180.             WNext();
  181.  
  182.             if (isdigit(c))
  183.             {
  184.             digitsafter = 1;
  185.             dowloop(isdigit);
  186.             }
  187.             }
  188.  
  189.         if ((width > 0) &&
  190.             ((c == 'e') || (c == 'E')))
  191.             {
  192.             hasexponent = 1;
  193.             WNext();
  194.  
  195.             if ((width > 0) &&
  196.             ((c == '-') || (c == '+')))
  197.             WNext();
  198.  
  199.             if ((width > 0) && isdigit(c))
  200.             dowloop(isdigit);
  201.  
  202.             else
  203.             goodpattern = 0;
  204.             }
  205.  
  206.         if (!((digitsbefore &&
  207.                (hasdecimal ||
  208.             hasexponent)) ||
  209.               digitsafter))
  210.             goodpattern = 0;
  211.  
  212.         break;
  213.  
  214.         // any string. leading white
  215.         // space was tossed above
  216.         case 's':
  217.         if (width > 0)
  218.             dowloop(!isspace);
  219.         break;
  220.  
  221.         // a scanset
  222.         case '[':
  223.         int x = 0;
  224.         char *patbegin = pattern;
  225.         if (pattern[1] == '^')
  226.             {
  227.             x = 1;
  228.             patbegin++;
  229.             }
  230.  
  231.         while ((width > 0) &&
  232.             checkcharset(patbegin, x, c))
  233.             WNext();
  234.  
  235.         // found the right # of chars?
  236.         if (width > 0)
  237.             goodpattern = 0;
  238.         pattern += x + 2 +
  239.             checkcharset(patbegin, 0, -1);
  240.         break;
  241.  
  242.         // any single character
  243.         case 'c':
  244.         while ((width > 0) &&
  245.                (c != EOF))
  246.             WNext();
  247.  
  248.         if (width > 0)
  249.             goodpattern = 0;
  250.         break;
  251.  
  252.         // match single %
  253.         case '%':
  254.         while ((width > 0) &&
  255.                (c == '%'))
  256.             WNext();
  257.  
  258.         if (width > 0)
  259.             goodpattern = 0;
  260.         break;
  261.  
  262.         // unknown pattern
  263.         default:
  264.         goodpattern = 0;
  265.         break;
  266.         }
  267.     break;
  268.  
  269.     // non-pattern, match the character
  270.     default:
  271.     if (c == p)
  272.         ebp->stossc();
  273.  
  274.     else
  275.         goodpattern = 0;
  276.     break;
  277.     }
  278. }
  279.  
  280.    ebp->resetbuffering();
  281.    return goodpattern;
  282.  
  283.